import datetime
import json
import os
from abc import ABC

import mysql.connector
from celery import Task
import app_init
import utils
from celery_app import app
from model import DeviceData

conn = app_init.getConn()
if not conn:
    exit

device_code_map = dict()
class Logger1:
    def __init__(self):
        self.file = open('server_task.log', 'a', encoding='utf-8')

    def info(self, info):
        self.file.write(f'{info}\n')
        self.file.flush()


logger = Logger1()
logger.info("task start")

def init():
    cursor = None
    try:

        cursor = conn.cursor()
        cursor.execute("select code,id from device_air_condition where type='分体式空调'")
        rows = cursor.fetchall()
        for row in rows:
            device_code_map[row[0]] = row[1]
        logger.info("初始化设备："+json.dumps(device_code_map))
    except Exception as e:
        cursor.close()
        logger.info(f"init error {e}")

init()



class MyTask(Task, ABC):
    """
    自定义一个类，继承自celery.Task
    exc: 失败时的错误的类型；
    task_id: 任务的id；
    args: 任务函数的位置参数；
    kwargs: 任务函数的关键字参数；
    einfo: 失败时的异常详细信息；
    retval: 任务成功执行的返回值；
    """

    def on_failure(self, exc, task_id, args, kwargs, einfo):
        """任务失败时执行"""
        logger.info(f"任务执行失败{args}, {kwargs}, {einfo}")

    def on_success(self, retval, task_id, args, kwargs):
        """任务成功时执行"""
        # logger.info("任务执行成功")
        pass

    def on_retry(self, exc, task_id, args, kwargs, einfo):
        """任务重试时执行"""
        logger.info("任务重试")


@app.task(base=MyTask)
def say_hello(x, y):
    return print(f"hello world {x + y}")


@app.task(base=MyTask)
def save_to_db():
    return "run_task"


def underscore_to_camelcase(s):
    parts = s.split('_')
    return parts[0] + ''.join(word.title() for word in parts[1:])


@app.task(base=MyTask)
def save_to_db_common_report(cr: dict):
    common_report = cr  # ObjectMaker.to_object(cr)
    cursor = None
    try:

        if common_report["reportType"] == "0605":
            # logger.info(f"save_to_db_common_report{cr}")
            cursor = conn.cursor()
            keys = "running_word ,total_electric_energy,month_prepaid_balance,month_subsidy_balance," \
                   "current_value,active_power,prepaid_balance,switch_word,voltage," \
                   "today_open_time,subsidy_balance,charge_balance,frequency,month_total_power," \
                   "report_time  ,temperature"
            # 执行 SQL 查询
            insert_query = f"INSERT INTO device_service_data (device_no ,{keys} )" \
                           " VALUES (%s,%s,%s,%s,%s," \
                           "       %s,%s,%s,%s,%s," \
                           "       %s,%s,%s,%s,%s," \
                           "        %s  ,%s)"
            keys = keys.replace("current_value", "current")
            v_dict = dict()
            for k in keys.split(","):
                k = underscore_to_camelcase(k.strip(" "))
                if "Word" not in k and "Time" not in k:

                    v_dict[k] = float(common_report["deviceData"][k])
                else:
                    v_dict[k] = common_report["deviceData"][k]
            from dateutil.parser import parse

            from datetime import datetime, timedelta
            date_obj = parse(v_dict["reportTime"])  # + timedelta(hours=8)
            v_dict["reportTime"] = date_obj
            data = [common_report["devNo"]] + list(v_dict.values())

            cursor.execute(insert_query, data)
            run_state, bd_mode, word = utils.get_run_word(v_dict["runningWord"])
            if bd_mode == "1":
                bd_mode = "01"
            else:
                bd_mode = "02"

            # deviceData = DeviceData()
            # deviceData.dataTime = v_dict["reportTime"]
            code = common_report["devNo"]
            # deviceData.voltage = v_dict["voltage"]
            # deviceData.currentTemp = v_dict["temperature"]
            # deviceData.electricCurrent = v_dict["current"]
            run_state = "1" if v_dict["current"] and float(v_dict["current"]) > 0.1 else "2"
            # deviceData.airConditioningStatus = run_state
            # deviceData.todayTime = v_dict["todayOpenTime"]
            # deviceData.monthTotalPower = v_dict["monthTotalPower"]

            if code not in device_code_map:
                cursor.execute("select id from device_air_condition where code=%s", [code])
                if cursor.fetchone() is None:
                    cursor.execute("insert into  device_air_condition(code,name,type) values(%s,%s,%s) ",
                                   [ code, '', '分体式空调'])
                    device_code_map[ code] = cursor.lastrowid
                    logger.info(f"新增分体式空调device_air_condition{code} 最新={device_code_map[ code] }")
            # cursor.execute(
            #     "insert into   device_data(code,data_time,air_conditioning_status,electric_current,air_condition_id,current_temp,"
            #     "today_open_time,month_total_power) values(%s,%s,%s,%s,%s,%s,%s,%s)",
            #     [deviceData.code, deviceData.dataTime, deviceData.airConditioningStatus, deviceData.electricCurrent,
            #      device_code_map[deviceData.code], deviceData.currentTemp, deviceData.todayTime,
            #      deviceData.monthTotalPower])
            update_query = "update device_air_condition set voltage=%s,power=%s,run_state=%s,electric_current=%s,temper=%s,data_time=%s,run_word=%s,bd_mode=%s where code=%s"
            data = [v_dict["voltage"], v_dict["activePower"], run_state, v_dict["current"], v_dict["temperature"],
                    v_dict["reportTime"], word, bd_mode] + [
                       common_report["devNo"]]
            logger.info(f"更新db：{data}")
            cursor.execute(update_query, data)
            # 提交事务
            conn.commit()
            cursor.close()
        elif common_report["reportType"] == "0002":
            pass
            # data = ([
            #     int(common_report["deviceData"]["status"]), common_report["deviceData"]["updateDateTime"],
            #     common_report["devNo"]
            # ])
            # update_query = "update device_gateway_data set status=%s,update_date_time=%s where device_no=%s"
            # cursor.execute(update_query, data)
            #
            # if cursor.rowcount == 0:
            #     logger.info(f"新增device_gateway_data数据 {data}")
            #     cursor.execute("insert into device_gateway_data (status,update_date_time,device_no) values(%s,%s,%s)",
            #                    data)
            # conn.commit()
    except  Exception as e:
        logger.info(f"处理数据错误{e}")
        conn.rollback()
    finally:
        if cursor:
            cursor.close()
    # rows = cursor.fetchall()
    #
    # # 打印查询结果
    # for row in rows:
    #     print(row)

    # print("save_to_db_common_report", common_report)
    pass


@app.task(base=MyTask)
def save_to_db_standard_read(cr):
    standard_read = cr  # ObjectMaker.to_object(cr)
    cursor = None
    try:
        cursor = conn.cursor()
        logger.info(f"save_to_db_standard_read:{standard_read}")
        code = standard_read["devNo"]
        result = standard_read["resultParams"]["result"]
        run_state = "1" if result["current"] and float(result["current"]) > 0.1 else "2"
        update_query = "update device_air_condition set voltage=%s,power=%s,run_state=%s,electric_current=%s," \
                       "temper=%s,data_time=%s   where code=%s "
        data = [result["voltage"], result["activePower"], run_state, result["current"], result["temperature"],
                datetime.datetime.now()] + [
                   code]

        cursor.execute(update_query, data)
        # 提交事务
        conn.commit()
        cursor.close()

        # "switchType": "0",
        # "powerFactor": "1.000",
        # "gridFrequency": "49.98",
        # "temperature": "22.4",
        # "activePower": "0.0000",
        # "current": "0.000",
        # "voltage": "221.7",
        # "combinedActiveTotalEnergy": "0.00
    except  Exception as e:
        logger.info(f"save_to_db_standard_read 处理数据错误{e}")
        conn.rollback()
    finally:
        if cursor:
            cursor.close()
